package tazmania.entity;

import java.nio.FloatBuffer;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.fixedfunc.GLPointerFunc;

import tazadum.engine.Entity;
import tazadum.engine.Interval;
import tazadum.engine.Signal;
import tazadum.engine.trigger.Adapter;
import tazadum.engine.trigger.IntegratingAdapter;
import tazadum.engine.util.BufferUtil;

public class MetaballsEntity implements Entity {
	class Metaball {
		int x;
		int y;
		int z;
		int cx; // center x
		int cy; // center y
		int cz; // center z
		int r; // radius
		double a; // angle
		double da; // delta angle
		int s; // size
	};

	final boolean SHOW_GRID = false;
	final boolean USE_BLEND = false;
	final int WIDTH = 640;
	final int HEIGHT = 480;
	final int NUM_BALLS = 10;
	final int MAX_RADIUS = 200;
	final int STEP_SIZE = 15;
	final int GRID_WIDTH = (WIDTH / STEP_SIZE);
	final int GRID_HEIGHT = (HEIGHT / STEP_SIZE + STEP_SIZE);
	final int GRID_DEPTH = (2 * HEIGHT / STEP_SIZE);
	final int THRESHOLD = 200;
	final int NUM_POINTS = 100000;

	FloatBuffer vbuffer = BufferUtil.newFloatBuffer(NUM_POINTS * 3);
	FloatBuffer cbuffer = BufferUtil.newFloatBuffer(NUM_POINTS * 4);
	int table[][] = null;
	Metaball mb[] = null;
	int grid[][][] = new int[GRID_WIDTH][GRID_HEIGHT][GRID_DEPTH];
	final int x[] = new int[12], y[] = new int[12], z[] = new int[12];

	private final Signal signal;
	private final int syncSignal;
	private final Adapter adapter = new IntegratingAdapter(0, 2);

	public MetaballsEntity(final Signal signal, final int syncSignal) {
		this.signal = signal;
		this.syncSignal = syncSignal;
	}

	@Override
	public void destroy(final GLAutoDrawable drawable) {
		// TODO Auto-generated method stub

	}

	@Override
	public void precalc(final GLAutoDrawable drawable, final float screenRatio) {
		int n, i;

		final int vrottab[][] = { { 3, 2, 6, 7, 0, 1, 5, 4 }, // rot-x
				{ 4, 0, 3, 7, 5, 1, 2, 6 }, // rot-y
				{ 3, 0, 1, 2, 7, 4, 5, 6 } }; // rot-z

		final int vmirrtab[][] = { { 3, 2, 1, 0, 7, 6, 5, 4 }, // y
				{ 1, 0, 3, 2, 5, 4, 7, 6 }, // x
				{ 4, 5, 6, 7, 0, 1, 2, 3 } };// z

		final int erottab[][] = { { 2, 11, 6, 10, 0, 9, 4, 8, 3, 1, 7, 5 }, // rot-x
				{ 8, 3, 10, 7, 9, 1, 11, 5, 4, 0, 6, 2 }, // rot-y
				{ 3, 0, 1, 2, 7, 4, 5, 6, 10, 8, 11, 9 } }; // rot-z

		final int emirrtab[][] = { { 2, 1, 0, 3, 6, 5, 4, 7, 10, 11, 8, 9 }, // y
				{ 0, 3, 2, 1, 4, 7, 6, 5, 9, 8, 11, 10 }, // x
				{ 4, 5, 6, 7, 0, 1, 2, 3, 8, 9, 10, 11 } };// z

		final int cases[][] = { { 1, 0, 8, 3, -1 }, // case 1
				{ 1 << 0 | 1 << 1, 9, 1, 8, 8, 1, 3, -1 }, // case 2
				{ 1 << 0 | 1 << 2, 3, 0, 8, 2, 1, 11, -1 }, // case 3
				{ 1 << 0 | 1 << 6, 0, 3, 8, 11, 6, 5, -1 }, // case 4
				{ 1 << 1 | 1 << 5 | 1 << 4, 7, 5, 1, 7, 1, 0, 7, 0, 8, -1 }, // case 5
				{ 1 << 0 | 1 << 1 | 1 << 6, 1, 9, 8, 1, 3, 8, 5, 11, 6, -1 }, // case 6
				{ 1 << 3 | 1 << 6 | 1 << 1, 10, 2, 3, 6, 11, 5, 0, 1, 9, -1 }, // case 7
				{ 1 << 0 | 1 << 1 | 1 << 5 | 1 << 4, 3, 1, 5, 5, 3, 7, -1 }, // case 8
				{ 1 << 7 | 1 << 0 | 1 << 4 | 1 << 5, 10, 6, 3, 6, 3, 0, 0, 6, 5, 5, 9, 0, -1 }, // case 9
				{ 1 << 3 | 1 << 0 | 1 << 6 | 1 << 5, 10, 2, 8, 8, 0, 2, 6, 11, 4, 4, 9, 11, -1 }, // case 10
				{ 1 << 0 | 1 << 4 | 1 << 5 | 1 << 6, 3, 7, 0, 7, 0, 11, 11, 0, 9, 11, 7, 6, -1 }, // case 11
				{ 1 << 3 | 1 << 4 | 1 << 1 | 1 << 5, 10, 2, 3, 8, 0, 1, 1, 8, 7, 7, 1, 5, -1 }, // case 12
				{ 1 << 0 | 1 << 7 | 1 << 2 | 1 << 5, 3, 0, 8, 5, 9, 4, 2, 11, 1, 6, 7, 10, -1 }, // case 13
				{ 1 << 7 | 1 << 4 | 1 << 1 | 1 << 5, 6, 10, 5, 10, 5, 0, 0, 8, 10, 0, 1, 5, -1 }, // case 14
		};

		/*
		 * Place the balls
		 */
		mb = new Metaball[NUM_BALLS];
		for (i = 0; i < NUM_BALLS; i++) {
			mb[i] = new Metaball();
			mb[i].cx = WIDTH / 2;// (int) (Math.random() * (WIDTH / 2) + WIDTH /
			// 4);
			mb[i].cy = HEIGHT / 2;// (int) (Math.random() * (HEIGHT / 2) +
			// HEIGHT / 4);
			mb[i].cz = 300;
			mb[i].r = (int) (Math.random() * MAX_RADIUS);
			mb[i].a = Math.random() * 2 * Math.PI * 100;
			mb[i].da = Math.random() * 2 * Math.PI / 7.0;
		}

		mb[0].r = 45;
		mb[0].a = 50.52276852577852f;
		mb[0].da = 0.2654801150158774f;
		mb[1].r = 70;
		mb[1].a = 21.03116605552072f;
		mb[1].da = 0.4459216478567842f;
		mb[2].r = 67;
		mb[2].a = 28.264864774518184f;
		mb[2].da = 0.8358896632867046f;
		mb[3].r = 82;
		mb[3].a = 160.86462044314638f;
		mb[3].da = 0.8598286081262546f;
		mb[4].r = 167;
		mb[4].a = 389.06396086620737f;
		mb[4].da = 0.74800676107137345f;
		mb[5].r = 79;
		mb[5].a = 113.3709980082713f;
		mb[5].da = 0.5871137061493902f;
		mb[6].r = 162;
		mb[6].a = 235.88855082315527f;
		mb[6].da = 0.5602363422048474f;
		mb[7].r = 153;
		mb[7].a = 496.0210064154912f;
		mb[7].da = -0.37331473790753833f;
		mb[8].r = 184;
		mb[8].a = 457.72718010737725f;
		mb[8].da = -0.1794540040734977f;
		mb[9].r = 83;
		mb[9].a = 357.06348135162114f;
		mb[9].da = 0.2641090072198746f;
		/*
		 * Generate table
		 */
		table = new int[256][50];// 50 is a big and safe number..
		for (n = 0; n < 256; n++) {
			int inv, rx, ry, rz, mx, my, mz, v, m;

			for (i = 0; i < table[n].length; i++) {
				table[n][i] = -1;
			}

			try {
				// for each case in cases[]
				for (m = 0; m < 14; m++) {
					v = cases[m][0];

					// try all combinations of rotation, mirror and invertsion,
					// then compare with n
					for (inv = 0; inv < 2; inv++) {
						int vinv;
						final int emx[] = new int[15];

						if (inv != 0) {
							vinv = (~v) & 255;
						} else {
							vinv = v;
						}

						// copy the edges to e incl -1
						for (i = 0; cases[m][i] != -1; i++) {
							emx[i] = cases[m][1 + i];
						}

						// for(i = 0; emx[i] != -1; i++) printf("%d ", emx[i]);
						// printf("\n");

						for (mx = 0; mx < 2; mx++) {
							int vmx;
							final int emy[] = new int[15];
							if (mx != 0) {
								vmx = 0;
								for (i = 0; i < 8; i++) {
									if (((vinv >> i) & 1) != 0) {
										vmx |= 1 << vmirrtab[1][i]; // 1=x
									}
								}

								for (i = 0; emx[i] != -1; i++) {
									emx[i] = emirrtab[1][emx[i]];
								}
							} else {
								vmx = vinv;
							}

							// memcpy(emy, emx, sizeof(emx));
							System.arraycopy(emx, 0, emy, 0, emx.length);
							for (my = 0; my < 2; my++) {
								int vmy;
								final int emz[] = new int[15];
								if (my != 0) {
									vmy = 0;
									for (i = 0; i < 8; i++) {
										if (((vmx >> i) & 1) != 0) {
											vmy |= 1 << vmirrtab[0][i]; // 0=y
										}
									}

									for (i = 0; emy[i] != -1; i++) {
										emy[i] = emirrtab[0][emy[i]];
									}
								} else {
									vmy = vmx;
								}

								// memcpy(emz, emx, sizeof(emx));
								System.arraycopy(emy, 0, emz, 0, emy.length);
								for (mz = 0; mz < 2; mz++) {
									int vmz, vrx;
									final int erx[] = new int[15];
									if (mz != 0) {
										vmz = 0;
										for (i = 0; i < 8; i++) {
											if (((vmy >> i) & 1) != 0) {
												vmz |= 1 << vmirrtab[2][i]; // 2=z
											}
										}

										for (i = 0; emz[i] != -1; i++) {
											emz[i] = emirrtab[2][emz[i]];
										}
									} else {
										vmz = vmy;
									}

									vrx = vmz;
									// memcpy(erx, emz, sizeof(emz));
									System.arraycopy(emz, 0, erx, 0, emz.length);
									for (rx = 0; rx < 4; rx++) {
										int tmp, vry;
										final int ery[] = new int[15];
										if (rx != 0) {
											tmp = 0;
											for (i = 0; i < 8; i++) {
												if (((vrx >> i) & 1) != 0) {
													tmp |= 1 << vrottab[0][i]; // 0=x
												}
											}

											for (i = 0; erx[i] != -1; i++) {
												erx[i] = erottab[0][erx[i]];
											}
										} else {
											tmp = vrx;
										}
										vrx = tmp;

										vry = vrx;
										// memcpy(ery, erx, sizeof(erx));
										System.arraycopy(erx, 0, ery, 0, erx.length);
										for (ry = 0; ry < 4; ry++) {
											int vrz;
											final int erz[] = new int[15];
											if (ry != 0) {
												tmp = 0;
												for (i = 0; i < 8; i++) {
													if (((vry >> i) & 1) != 0) {
														tmp |= 1 << vrottab[1][i]; // 1=y
													}
												}

												for (i = 0; ery[i] != -1; i++) {
													ery[i] = erottab[1][ery[i]];
												}
											} else {
												tmp = vry;
											}
											vry = tmp;

											vrz = vry;
											// memcpy(erz, ery, sizeof(ery));
											System.arraycopy(ery, 0, erz, 0, ery.length);
											for (rz = 0; rz < 4; rz++) {
												if (rz != 0) {
													tmp = 0;
													for (i = 0; i < 8; i++) {
														if (((vrz >> i) & 1) != 0) {
															tmp |= 1 << vrottab[2][i]; // 2=z
														}
													}

													for (i = 0; erz[i] != -1; i++) {
														erz[i] = erottab[2][erz[i]];
													}
												} else {
													tmp = vrz;
												}
												vrz = tmp;

												if (n == vrz) {

													for (i = 0; erz[i] != -1; i++) {
														table[n][i] = erz[i];
													}

													throw new Exception();
												}
											}
										}
									}
								}
							}
						}
					}
				}
			} catch (final Exception e) {
				// done
			}
		}
	}

	@Override
	public void update(final GLAutoDrawable drawable, final float globalTime, final float localTime, final float dt, final Interval interval) {
		final GL2 gl = drawable.getGL().getGL2();
		int i, gx, gy, gz, npoly = 0;

		vbuffer.rewind();
		cbuffer.rewind();
		/*
		 * vbuffer.clear(); cbuffer.clear(); vbuffer.reset(); cbuffer.reset();
		 */

		final float time = localTime + adapter.convert(signal.channel(syncSignal) * dt);
		final float r = 1;// (float) Math.sin(time) * 0.5f + 0.5f;
		final float g = (float) Math.sin(time * 2 + 3.14) * 0.5f + 0.5f;
		final float b = (float) Math.sin(time) * 0.5f + 0.5f;
		// Move balls
		for (i = 0; i < NUM_BALLS; i++) {
			final float a = (float) (mb[i].a + mb[i].da * time);
			mb[i].x = (int) (mb[i].cx + mb[i].r * Math.sin(a));
			mb[i].y = (int) (mb[i].cy + mb[i].r * Math.cos(a));
			// mb[i].y = (int) (mb[i].cy + mb[i].r *
			// Math.cos(a)*(1+((signal.channel(Signal.CHANNEL_SYNTH_ENV_2)==0)?0:1)));
			mb[i].z = (int) (mb[i].cz + mb[i].r * Math.cos(a / 2.0));

		}

		// calculate
		for (gz = 0; gz < GRID_DEPTH; gz++) {
			for (gy = 0; gy < GRID_HEIGHT; gy++) {
				for (gx = 0; gx < GRID_WIDTH; gx++) {
					int x, y, z;
					x = gx * STEP_SIZE;
					y = gy * STEP_SIZE;
					z = gz * STEP_SIZE;

					grid[gx][gy][gz] = 0;
					for (i = 0; i < NUM_BALLS; i++) {
						grid[gx][gy][gz] += 400000 / ((mb[i].x - x) * (mb[i].x - x) + (mb[i].y - y) * (mb[i].y - y) + (mb[i].z - z)
								* (mb[i].z - z) + 1);
					}
				}
			}
		}

		// draw
		for (gz = 0; gz < GRID_DEPTH - 1; gz++) {
			for (gy = 0; gy < GRID_HEIGHT - 1; gy++) {
				for (gx = 0; gx < GRID_WIDTH - 1; gx++) {
					int y2, m, mask = 0, v1, v2, v3, v4, v5, v6, v7, v8;
					float k;

					v1 = grid[gx + 0][gy + 0][gz + 0];
					v2 = grid[gx + 1][gy + 0][gz + 0];
					v3 = grid[gx + 1][gy + 1][gz + 0];
					v4 = grid[gx + 0][gy + 1][gz + 0];
					v5 = grid[gx + 0][gy + 0][gz + 1];
					v6 = grid[gx + 1][gy + 0][gz + 1];
					v7 = grid[gx + 1][gy + 1][gz + 1];
					v8 = grid[gx + 0][gy + 1][gz + 1];

					mask |= (v1 > THRESHOLD) ? 1 << 0 : 0; // v1
					mask |= (v2 > THRESHOLD) ? 1 << 1 : 0; // v2
					mask |= (v3 > THRESHOLD) ? 1 << 2 : 0; // v3
					mask |= (v4 > THRESHOLD) ? 1 << 3 : 0; // v4
					mask |= (v5 > THRESHOLD) ? 1 << 4 : 0; // v5
					mask |= (v6 > THRESHOLD) ? 1 << 5 : 0; // v6
					mask |= (v7 > THRESHOLD) ? 1 << 6 : 0; // v7
					mask |= (v8 > THRESHOLD) ? 1 << 7 : 0; // v8

					// e1
					m = v1; // v1
					y2 = v2; // v2
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[0] = (int) (gx * STEP_SIZE + (THRESHOLD - m) / k);
						y[0] = gy * STEP_SIZE;
						z[0] = gz * STEP_SIZE;
					}

					// e4
					m = v1; // v1
					y2 = v4; // v4
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[3] = gx * STEP_SIZE;
						y[3] = (int) (gy * STEP_SIZE + (THRESHOLD - m) / k);
						z[3] = gz * STEP_SIZE;
					}

					// e9
					m = v1; // v1
					y2 = v5; // v5
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[8] = gx * STEP_SIZE;
						y[8] = gy * STEP_SIZE;
						z[8] = (int) (gz * STEP_SIZE + (THRESHOLD - m) / k);
					}

					// e3
					m = v3; // v3
					y2 = v4; // v4
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[2] = (int) (gx * STEP_SIZE + STEP_SIZE - (THRESHOLD - m) / k);
						y[2] = gy * STEP_SIZE + STEP_SIZE;
						z[2] = gz * STEP_SIZE;
					}

					// e2
					m = v3; // v3
					y2 = v2; // v2
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[1] = gx * STEP_SIZE + STEP_SIZE;
						y[1] = (int) (gy * STEP_SIZE + STEP_SIZE - (THRESHOLD - m) / k);
						z[1] = gz * STEP_SIZE;
					}

					// e12
					m = v3; // v3
					y2 = v7; // v7
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[11] = gx * STEP_SIZE + STEP_SIZE;
						y[11] = gy * STEP_SIZE + STEP_SIZE;
						z[11] = (int) (gz * STEP_SIZE + (THRESHOLD - m) / k);
					}

					// e5
					m = v6; // v6
					y2 = v5; // v5
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[4] = (int) (gx * STEP_SIZE + STEP_SIZE - (THRESHOLD - m) / k);
						y[4] = gy * STEP_SIZE;
						z[4] = gz * STEP_SIZE + STEP_SIZE;
					}

					// e6
					m = v6; // v6
					y2 = v7; // v7
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[5] = gx * STEP_SIZE + STEP_SIZE;
						y[5] = (int) (gy * STEP_SIZE + (THRESHOLD - m) / k);
						z[5] = gz * STEP_SIZE + STEP_SIZE;
					}

					// e10
					m = v6; // v6
					y2 = v2; // v2
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[9] = gx * STEP_SIZE + STEP_SIZE;
						y[9] = gy * STEP_SIZE;
						z[9] = (int) (gz * STEP_SIZE + STEP_SIZE - (THRESHOLD - m) / k);
					}

					// e7
					m = v8; // v8
					y2 = v7; // v7
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[6] = (int) (gx * STEP_SIZE + (THRESHOLD - m) / k);
						y[6] = gy * STEP_SIZE + STEP_SIZE;
						z[6] = gz * STEP_SIZE + STEP_SIZE;
					}

					// e8
					m = v8; // v8
					y2 = v5; // v5
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[7] = gx * STEP_SIZE;
						y[7] = (int) (gy * STEP_SIZE + STEP_SIZE - (THRESHOLD - m) / k);
						z[7] = gz * STEP_SIZE + STEP_SIZE;
					}

					// e11
					m = v8; // v8
					y2 = v4; // v4
					if ((m > THRESHOLD) ^ (y2 > THRESHOLD)) {
						k = (y2 - m) / (float) STEP_SIZE;
						x[10] = gx * STEP_SIZE;
						y[10] = gy * STEP_SIZE + STEP_SIZE;
						z[10] = (int) (gz * STEP_SIZE + STEP_SIZE - (THRESHOLD - m) / k);
					}

					i = 0;
					while (table[mask][i] != -1) {
						float c;
						final int q = table[mask][i];

						// c = (float) (z[q] - 220) / 300;
						//
						// if (c < 0.1) {
						// c = 0.1f;
						// } else if (c > 1) {
						// c = 1;
						// }

						// gl.glColor3f(c, c * (float) (Math.sin(localTime) + 1)
						// / 2, c * (float) (Math.sin(localTime * 2) + 1) / 2);

						final float ax = x[q] - WIDTH / 2;
						final float ay = y[q] - HEIGHT / 2;
						final float az = z[q] - 100;

						c = 0.1f;
						if (az >= 0) {
							c = 0.1f + az * az * 0.0025f * 0.0025f;
						}
						cbuffer.put(c * r);
						cbuffer.put(c * g);
						cbuffer.put(c * b);
						// cbuffer.put(c * (float) (Math.sin(time) + 1) / 2);
						// cbuffer.put(c * (float) (Math.sin(time * 2) + 1) / 2);
						if (USE_BLEND) {
							cbuffer.put(.3f);
						}

						// gl.glVertex3f(x[q] - WIDTH / 2, y[q] - HEIGHT / 2 +
						// 20, z[q] - 300);
						vbuffer.put(ax);
						vbuffer.put(ay);
						vbuffer.put(z[q] - 300);

						i++;
						npoly++;
					}
				}
			}
		}

		vbuffer.rewind();
		cbuffer.rewind();

		gl.glClearDepth(1.0f);
		gl.glEnable(GL2GL3.GL_DEPTH_TEST);

		gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
		gl.glPushMatrix();
		gl.glLoadIdentity();
		gl.glOrtho(-WIDTH / 2, WIDTH / 2, HEIGHT / 2, -HEIGHT / 2, 1000, -1000);

		gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
		gl.glPushMatrix();
		gl.glLoadIdentity();
		gl.glEnable(GL2.GL_DEPTH);
		gl.glShadeModel(GL2.GL_SMOOTH);

		gl.glRotatef(180 + localTime, 0, 1, 0);

		if (USE_BLEND) {
			gl.glEnable(GL.GL_BLEND);
			gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
		}

		gl.glPolygonMode(GL2GL3.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
		gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
		gl.glVertexPointer(3, GL.GL_FLOAT, 0, vbuffer);
		gl.glEnableClientState(GLPointerFunc.GL_COLOR_ARRAY);
		if (USE_BLEND) {
			gl.glColorPointer(4, GL.GL_FLOAT, 0, cbuffer);
		} else {
			gl.glColorPointer(3, GL.GL_FLOAT, 0, cbuffer);
		}
		gl.glDrawArrays(GL.GL_TRIANGLES, 0, npoly);

		if (USE_BLEND) {
			gl.glDisable(GL.GL_BLEND);
		}

		if (SHOW_GRID) {
			vbuffer.rewind();
			gl.glEnable(GL.GL_LINE_SMOOTH);
			gl.glColor3f(0, 0, 0);
			gl.glPolygonMode(GL2GL3.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
			gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
			gl.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY);
			gl.glVertexPointer(3, GL.GL_FLOAT, 0, vbuffer);
			gl.glDrawArrays(GL.GL_TRIANGLES, 0, npoly);
		}

		// gl.glMatrixMode(GL2.GL_MODELVIEW);
		gl.glPopMatrix();
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glPopMatrix();
	}
}
